import React from 'react'
import { connect } from 'react-redux'
import {Modal, message, Button, Upload, Icon} from 'antd';
import {messages} from "share/common";
import ImportErrInfo from "components/template/import-err-info";
import FileSaver from "file-saver";
import ImportModalService from 'components/template/import-modal-ie/import-modal.service'
import config from "config";
import FileUpload from "components/template/ie-file-upload/file-upload";
import constants from "share/constants";
import 'styles/components/template/import-modal/import-modal.scss'
import errorMessage from "share/errorMessage"
/*
* 针对导入，要求后端以下提供四个接口
* 1.导入的模块下载
* 2.模板导入
* 3.导入错误信息实时查询（这个是通用的，后端一般不提供，可以查看前端页面中已有）
* 4.一次性导出错误信息
* */

class ImportModal extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      visible: false,
      fileList: [],
      errorsList: [],
      transactionOID: null,
      progressImportErr: 1,
      showImportErr: false,
      exportLoading: false,
      callBackContent: null,
      requestGapTime : 500,
      downloadingList: {},
      fileUploading: false,
    };
  }

  componentWillMount(){
    this.setDownloadingList();
  }

  onImportModalCancel = () => {
    this.setState({
      visible: false,
      callBackContent: null,
      fileList: [],
    });
    this.props.onCancel();
  };

  setDownloadingList = () => {
    const {downloadingList} = this.state;
    const {templates} = this.props;
    templates.length && templates.map(item => {
      downloadingList[item.downloading] = false;
    });
    this.setState({
      downloadingList,
    });
  };

  //导入时错误信息
  showTransactionLogDialog = (transactionOID) => {
    const {showErrUrl} = this.props;
    this.state.requestGapTime += this.state.requestGapTime;
    ImportModalService.checkError(showErrUrl, transactionOID)
      .then((res) => {
        let data = res.data;
        if (data.totalEntities === 0) {
          message.success(messages("common.operate.success"));
          this.hideImportErrInfo();
          return;
        } else {
          let errors = data.errors;
          let errorsList = this.getErrorDataByErrors(errors);
          let progressImportErr = this.getProgressByData(data);
          this.setState({
            progressImportErr,
            errorsList
          });
          if ((data.successEntities + data.failureEntities) !== data.totalEntities) {
            setTimeout(() => {
              //请求频率涉及到一个算法
              this.showTransactionLogDialog(this.state.transactionOID);   // 将参数传给dialog
            }, this.state.requestGapTime)
          } else {
            //导入完成了
            if(JSON.stringify(res.data.errors) === '{}'){
              message.success(messages("common.operate.success"));
              this.hideImportErrInfo();
              this.props.onGetList();
            }
          }
        }
      })
  };

  //获取百分进度
  getProgressByData = (data) => {
    return Math.round((data.failureEntities + data.successEntities) * 100 / data.totalEntities);
  };

//通过错误信息，解析成表格
  getErrorDataByErrors = (errs, isSpecial = false) => {
    let data = [];
    if (isSpecial) {
      Object.keys(errs).map(item => {
        let row = {};
        row.line = item;
        row.msg = errs[item];
        data.push(row);
      })
    } else {
      for (let key in errs) {
        let row = {};
        row.line = errs[key];
        if (row.line.length > 1) {
          let _line = [];
          for (let i = 0; i < row.line.length; i++) {
            _line.push(row.line[i]);
            if (i < row.line.length - 1) {
              _line.push(",");
            }
          }
          row.line = _line;
        }
        row.msg = key;
        data.push(row);
      }
    }
    return data;
  };

  //人员导入的错误信息-start
  showImportErrInfo = () => {
    this.setState({
      showImportErr: true
    });
  };

  hideImportErrInfo = () => {
    this.setState({
      errorsList: [],
      fileList: [],
      visible: false,
      showImportErr: false
    }, () =>{
      this.props.onCancel();
    });
  };

  //导入的错误信息
  showExportFailedLog = () => {
    const {transactionOID} = this.state;
    const {exportErrUrl} = this.props;
    this.setState({
      exportLoading: true
    });
    ImportModalService.exportError(exportErrUrl, transactionOID)
      .then((res) => {
        this.setState({
          exportLoading: false
        });
        let b = new Blob([res.data], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"});
        let name = messages('components.key489')/*错误信息*/;
        FileSaver.saveAs(b, `${name}.xlsx`);
      })
      .catch((res) => {
        this.setState({
          exportLoading: false
        });
      });
  };

  handleChange = (response) => {
    const { fileList } = this.state;
    fileList.push(response);
    const { hasErrInfo,  callBackResult} = this.props;
    this.setState({
      fileList,
    }, () => {
      message.success(`${messages('components.key399'/*上传成功*/)}`);
      let transactionOID = response.transactionOID;
      if(hasErrInfo && transactionOID){
        this.setState({
          transactionOID,
        });
        this.showImportErrInfo();
        this.state.requestGapTime = 500;
        this.showTransactionLogDialog(transactionOID);
      }else if(callBackResult){
        let result = callBackResult(response);
        this.setState({
          callBackContent: result,
        })
      }else{
        this.setState({
          visible: false,
          fileList: [],
        }, () =>{
          this.props.onCancel();
        });
      }
    });
  };

  beforeUpload = (file) => {
    const { beforeUpload, fileSize} = this.props;
    if(beforeUpload){
      let list =  beforeUpload(file);
      this.setState({fileList: list});
    }else{
      if(file.name.endsWith('.xls') || file.name.endsWith('.xlsx')){
        if (fileSize) {  //文件的大小
          const isLtSize = file.size / 1024 / 1024 <= fileSize;
          if (!isLtSize) {
            message.error(messages('components.key893',{arg1:fileSize})/*文件不能超过{arg1}M*/);
          }else{
            this.setState({fileList: [file]});
          }
        }
      } else{
        message.error(messages('setting.key378'/*请上传Excel文件*/));
      }
    }
    return false;
};

  //下载模板
  downloadTemplate = item => {
    const { downloadingList } = this.state, { downloading, downloadMethod, downloadUrl, templateName, params } = item;
    downloadingList[downloading] = true;
    this.setState({
      downloadingList,
    }, () => {
      ImportModalService.downloadTemplate(downloadMethod || 'get', downloadUrl, params || {})
        .then((res) => {
          let file = new Blob([res.data], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"});
          FileSaver.saveAs(file, `${templateName ? templateName : messages('components.key894')/*导入模板*/}.xls`);
          downloadingList[downloading] = false;
          this.setState({
            downloadingList,
          });
        })
        .catch((res) => {
          downloadingList[downloading] = false;
          this.setState({
            downloadingList,
          });
        });
    });
  };

  handleFileUpload = () => {
    const { fileList } = this.state;
    const { hasErrInfo, callBackResult, uploadUrl, uploadParams, uploadAsync } = this.props;
    const formData = new FormData();
    formData.append('file', fileList[0]);
    if(uploadParams){
      for(let attr in uploadParams) {
        formData.append(`${attr}`, uploadParams[attr]);
      }
    }
    this.setState({
      fileUploading: true,
    });
    ImportModalService.importTemplate(uploadUrl, formData)
      .then((res) => {
        if (uploadAsync) { //异步上传
          this.listenUploadStatus(res.data.transactionOID || res.data);
          return
        }
        this.setState({ fileUploading: false });
        message.success(`${messages('components.key399'/*上传成功*/)}`);
        let transactionOID = res.data.transactionOID;
        if(hasErrInfo && transactionOID){
          this.setState({
            transactionOID,
          });
          this.showImportErrInfo();
          this.state.requestGapTime = 500;
          this.showTransactionLogDialog(transactionOID);
        }else if(callBackResult){
          let result = callBackResult(res);
          this.setState({
            callBackContent: result,
          })
        }else{
          this.setState({
            visible: false,
            fileList: [],
          }, () =>{
            this.props.onCancel();
          });
        }
      })
      .catch((res) => {
        this.setState({
          fileUploading: false,
        });
      })
  };

  //监听导入状态：PARSING_FILE(1001), PROCESS_DATA(1002), DONE(1003), ERROR(1004), CANCELLED(1005)
  listenUploadStatus = (transactionOID) => {
    const { listenUrl } = this.props;
    ImportModalService.listenUploadStatus(listenUrl, transactionOID).then(res => {
      if (res.data.status === 1004) { //ERROR
        this.setState({ fileUploading: false });
        message.error(messages('components.key475'/*导入失败，请重试*/))
      } else if (res.data.status === 1003) { //DONE
        if (res.data.failureEntities && res.data.failureEntities > 0) { //行错误
          this.setState({
            fileUploading: false,
            errorsList: this.getErrorDataByErrors(res.data.errors || JSON.parse(res.data.errorDetail), true),
            progressImportErr: 100,
            transactionOID
          }, this.showImportErrInfo)
        } else {
          this.setState({
            fileUploading: false,
            visible: false,
            fileList: [],
          });
          message.success(`${messages('components.key399'/*上传成功*/)}`);
          this.props.onCancel()
        }
      } else {
        setTimeout(() => {
          this.listenUploadStatus(transactionOID)
        }, 1000)
      }
    }).catch(e => {
      errorMessage(e.response);
      this.setState({ fileUploading: false })
    })
  };

  render(){
    const {visible, progressImportErr, errorsList, showImportErr, exportLoading, callBackContent, downloadingList,
      fileList, fileUploading} = this.state;
    const {attachmentType, downLinks, leftContent, title, templates, rightContent, authToken, uploadUrl, accept,
      showMaxNum, disabled, maxNum, hasErrInfoButton, buttonName, uploadParams, buttonDisabled, isNormalModal} = this.props;
    let data = uploadParams ? uploadParams : attachmentType;
    const props = {
      onRemove: (file) => {
        this.setState(({fileList}) => {
          const index = fileList.indexOf(file);
          const newFileList = fileList.slice();
          newFileList.splice(index, 1);
          return {
            fileList: newFileList,
          };
        });
      },
    };
    return(
      <div style={{display: "inline-block"}}>
        <Button onClick={() => {this.setState({visible: true})}} type={isNormalModal ? 'primary' : 'default'} disabled={buttonDisabled}>{buttonName}</Button>
        <Modal closable
               width={downLinks || leftContent ? 760 : 520}
               className="import-modal"
               title={title}
               visible={visible}
               onCancel={this.onImportModalCancel}
               destroyOnClose={true}
               footer={isNormalModal ? <div>
                 <Button onClick={this.onImportModalCancel}>{messages('common.cancel')/*取消*/}</Button>
                 <Button type="primary"
                         onClick={this.handleFileUpload}
                         disabled={disabled || !fileList.length}
                         loading={fileUploading}>{messages('components.key455')/*确认*/}</Button>
               </div> : null}>
          <div>
            {
              callBackContent ?
                callBackContent :
                <div>
                  {
                    downLinks || leftContent
                      ?
                      <div className='left-content'
                           style={downLinks || leftContent ? {width:340, float: 'left'} : {}}>
                        <div className={isNormalModal ? "" : "bottom-left-class"}>
                          <div className="bottom-class top-class">
                            {leftContent}
                          </div>
                          <div className="bottom-class top-class">
                            {downLinks}
                          </div>
                          {
                            templates.length ? templates.map(item => {
                              return(
                                <div>
                                  {
                                    item.style ?
                                      <div style={item.style}
                                           onClick={() => this.downloadTemplate(item)}>
                                        {item.downloadName}
                                      </div>
                                      :
                                      <Button icon="download"
                                              className='default-color-font'
                                              style={{border: 'none', margin: "10px 0"}}
                                              size={'small'}
                                              loading={downloadingList[item.downloading]}
                                              onClick={() => this.downloadTemplate(item)}>
                                        {item.downloadName}
                                      </Button>
                                  }
                                </div>
                              )
                            })
                              : null
                          }
                        </div>
                      </div>
                      : null
                  }
                  <div style={downLinks || leftContent ? {width: 340, float: 'right'} : {}}>
                    <div className={isNormalModal ? "" : "bottom-left-class top-class"}>
                      <div className={isNormalModal ? "" : "bottom-class top-class"}>
                        {rightContent}
                      </div>
                      <div className={isNormalModal ? "top-class" : "bottom-class top-class"}>
                        {
                          window.ISIE9 ?
                          <FileUpload
                            onChange={this.handleChange}
                            token={authToken.access_token}
                            data={data}
                            beforeUpload={this.beforeUpload}
                            uploadUrl={uploadUrl}
                            disabled={disabled || fileList.length >= maxNum}
                            accept={accept}/>
                            :
                            <div>
                              <Upload {...props} fileList={fileList} beforeUpload={this.beforeUpload}>
                                <Button>
                                  <Icon type="upload"/>
                                  {messages('enterprise-manage.key42'/*选择一个文件*/)}
                                </Button>
                              </Upload>
                              {
                                !isNormalModal &&
                                <Button
                                  style={{margin: "10px 0"}}
                                  type="primary"
                                  onClick={this.handleFileUpload}
                                  disabled={disabled || !fileList.length}
                                  loading={fileUploading}>
                                  {this.state.fileUploading ? messages('enterprise-manage.key43'/*上传中*/) : messages('enterprise-manage.key44'/*开始上传*/)}
                                </Button>
                              }
                              {
                                showMaxNum && (
                                  <div>{messages('common.max.upload.attachment', {max: maxNum})/*最多上传 {max} 个附件*/}</div>
                                )
                              }
                            </div>
                        }
                      </div>
                    </div>
                  </div>
                  <div className='clear'/>
                </div>
            }
          </div>
        </Modal>
        <ImportErrInfo
          progress={progressImportErr}
          cancel={this.hideImportErrInfo}
          exportErrInfo={this.showExportFailedLog}
          errorsList={errorsList}
          visible={showImportErr}
          exportLoading={exportLoading}
          exportBtn={hasErrInfoButton}/>
      </div>
    )
  }
}

ImportModal.contextTypes = {
  router: React.PropTypes.object,
};

ImportModal.propTypes = {
  uploadUrl: React.PropTypes.string,  //上传文件时的URL
  showErrUrl: React.PropTypes.string,  //展示错误信息的URL
  exportErrUrl: React.PropTypes.string,  //导出错误信息的URL
  onCancel: React.PropTypes.func,  //点击取消
  downLinks: React.PropTypes.any,  //需要下载的模板列表
  leftContent: React.PropTypes.any,  //左边区域内容
  rightContent: React.PropTypes.any,  //右边区域内容
  showMaxNum: React.PropTypes.bool, //是否显示最大上传文件的数量
  maxNum: React.PropTypes.number,  //最大上传文件的数量
  fileSize: React.PropTypes.number,  //文件最大不能超过多少M
  uploadParams: React.PropTypes.object, //上传文件时需要的额外的参数
  accept: React.PropTypes.string,//附件只接受的类型
  disabled: React.PropTypes.bool,//上传文件按钮 disabled
  buttonDisabled: React.PropTypes.bool,//导入按钮 disabled
  hasErrInfo: React.PropTypes.bool,//是否展示错误信息
  hasErrInfoButton: React.PropTypes.bool,//是否展示 导出错误信息按钮
  title: React.PropTypes.any,//导入时的模态框title
  callBackResult: React.PropTypes.func,//上传成功后的回调，返回DOM节点
  beforeUpload: React.PropTypes.func,//上传前的校验,返回数组
  templates: React.PropTypes.array,//需要下载的模板list
  buttonName: React.PropTypes.string,//导入组件的按钮名称
  isNormalModal: React.PropTypes.bool, //是否为正常的modal，即footer有确定 取消按钮
  uploadAsync: React.PropTypes.bool, //上传文件的接口是否是异步的
  listenUrl: React.PropTypes.string,    //监听上传接口状态的URL
};
ImportModal.defaultProps = {
  attachmentType: "OTHER",
  accept: constants.acceptFileTypes,
  uploadUrl: `${config.baseUrl}/api/upload/attachment/v2`,
  exportErrUrl: '',
  showErrUrl: '',
  /*
  * showErrorUrl: "错误信息展示路径"，路径需为baseUrl后面完整的路径，参数需用 ${参数} 包裹
  * exportErrUrl: "错误信息下载路径"，路径格式同showErrorUrl
  * 如"/supplier/api/batch/transaction/logs?transactionOID=${transactionOID}"
  * 或"/api/batch/transaction/logs/v2/${transactionOID}"
  * */
  showMaxNum: true,
  disabled: false,
  buttonDisabled: false,
  hasErrInfo: false,
  hasErrInfoButton: true,
  maxNum: 1,
  fileSize: 2,
  buttonName: messages('setting.key304'/*导入*/),
  title: messages('setting.key304'/*导入*/),
  downLinks: <div/>,
  templates: [],// [{downloadName: "需要下载的模板名称", templateName: "下载好的模板名称", downloadUrl: "下载的路径", style: {自定义样式}}]
  leftContent:
    (
      <div>
        <div className={"bottom-class"}><h4>{messages('setting.key384'/*创建模板*/)}</h4></div>
        <div className="bottom-class">1.{messages('components.key830')/*下载所需模板*/}</div>
        <div className="bottom-class">2.{messages('setting.key387'/*严格按照导入模板整理数据，检查必输事项是否缺少数据*/)}</div>
        <div className="bottom-class">{messages('setting.key388'/*3.关闭Excel文件后，方可进行数据导入*/)}</div>
      </div>
    ),

  rightContent:
    (
      <div>
        <div><h4>{/*上传模板*/}{messages('setting.key308')}</h4></div>{/*上传模板*/}
        <div>1.{messages('components.key831')/*点击【上传文件】按钮，选择更新过的模板文件（文件不能大于2M）,并点击确定*/}</div>
      </div>
    ),

  onCancel: () => {},
  uploadAsync: false,
  listenUrl: `${config.budgetUrl}/api/budget/batch/transaction/logs`,
  isNormalModal: false
};

function mapStateToProps(state) {
  return {
    authToken: state.main.authToken
  }
}

export default connect(mapStateToProps)(ImportModal);
